def assert_return_formatted(x):
    x0 = x.split(" ")
    assert len(x0) == 2
    return [int(x0[0]), int(x0[1])]

import subprocess

def execute(command):
    program=subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    stdout,stderr=program.communicate()
    #print(stdout,stderr)
    return stdout, stderr

def get_password(user_index):
    user = "james{}deutschland".format(user_index)
    stdout, stderr = execute(["bash","-c","cat ~/.git-credentials"])
#    print(stdout)
    stdout = stdout.decode("utf-8").split("\n")
#    print(stdout)
    stdout = [x for x in stdout if user in x]
#    print(stdout)
    candidate = stdout[0]
    return candidate

def checker():
    with open("candidates_list","r") as f:
        return [assert_return_formatted(x) for x in [z for z in f.read().split("\n") if len(z) > 0]]

import os
#import multiprocessing
import schedule
import time
def get_collection(target_user,target_dir):
    collection = "james{}deutschland/{}".format(target_user,target_dir)
    return collection
def run_against(collection):
    # try cloning into given directory?
    print("cloning missing target:",collection)
    #collection = get_collection(target_user,target_dir)
    cmd = "git clone https://github.com/{} {}".format(collection,collection)
    os.system(cmd)
def run_regular(target_user,target_dir):
    collection = get_collection(target_user,target_dir)
    print("initializing daemon script for:",collection)
    script_name ="{}.sh".format(collection)
    if not os.path.exists(script_name):
        commit_url = get_password(target_user)
        commit_url +="/"
        commit_url += collection
        commit_url +=".git"
        with open(script_name,"w+") as f:
            f.write("cd {} && bash fetch.sh && bash autocommit.sh && git push {} master && bash delta_time.sh\n".format(target_dir, commit_url))
    cmd = script_name
    os.system("bash -c \"cd {} && bash {}.sh\"".format(collection.split("/")[0],target_dir))
def spare_run_regular(collection):
    # no need to run multiprocessing.
    target_user, target_dir = collection.split("/")
    target_user = target_user.replace("james","").replace("deutschland","")
    target_user = int(target_user)
    run_regular(target_user,target_dir)
#    for target_user,target_dir in target_pairs:
#        run_regular(target_user,target_dir)
#    multiprocessing.Process(target=run_regular,args=(target_dir,)).start()
def format_candidates(num_list):
    return [[x,"littlerepo{}".format(y)] for x,y in num_list]
def check_missing(_list):
    return [x for x in _list if not os.path.exists(x)]
online=[]
sleep_minutes=1
schedule_loop=30
current_loop=0
def operation():
    global online, sleep_minutes, schedule_loop, current_loop
    for x in range(len(online)):
        loop = x
        loop %= schedule_loop
        if loop == current_loop:
            candidate = online[x]
            print("running via scheduler every {} minutes at loop {}:".format(sleep_minutes, loop),candidate)
            spare_run_regular(candidate)
    current_loop+=1
    current_loop%=schedule_loop
init = True
schedule.every(sleep_minutes).minutes.do(operation)
prev_collections, prev_missing, prev_online = [], [], []
import copy
#delta=False
while True:
    new_list = checker()
    targets = format_candidates(new_list)
    collections = [get_collection(x,y) for x,y in targets]
    missing = check_missing(collections)
    prepare_online = [x for x in collections if x not in missing]
    online.clear()
    for x in prepare_online:
        online.append(x)
    def delta_printer():
        print("targets:",len(collections))
        print("missing:",missing)
        print("online:",len(online))
    def is_different(x,y):
        x0,y0 = set(x), set(y)
        return (len(x0.intersection(y0))!= len(x0)) or (len(x0) != len(y0))
    def delta():
        global prev_collections, prev_missing, prev_online
        is_delta = is_different(prev_collections, collections) or is_different(prev_missing, missing) or is_different(prev_online, online)
        prev_collections, prev_missing, prev_online = copy.deepcopy(collections), copy.deepcopy(missing), copy.deepcopy(online)
        return is_delta
    if init:
        delta_printer()
        delta()
#        for x in online:
#            print("running via init job:",x)
#            spare_run_regular(x)
        init = False
    else:
        if delta():
            print("candidates_list has been changed")
            delta_printer()
    for x in missing:
        run_against(x)
        print("running via init job for missing:",x)
        spare_run_regular(x)
    schedule.run_pending()
    time.sleep(5)
